package com.twu.biblioteca;

import javafx.util.Pair;

import java.io.BufferedReader;
import java.util.Collection;

public class BibliotecaApp {

    private IOHandler ioHandler;

    private Catalog<Book> inStockBooks;
    private Catalog<Movie> inStockMovies;

    private Collection<User> users;
    private User LoggedInUser;

    private Collection<Pair<Book,User>> booksAllocatedToUsers;

    public BibliotecaApp(Catalog<Book> inStockBooks,Catalog<Movie> inStockMovies, Collection<User> users,Collection<Pair<Book,User>> booksAllocatedToUsers)   //Constructor for production
    {
        ioHandler = new IOHandler();
        this.inStockBooks=inStockBooks;
        this.inStockMovies=inStockMovies;
        this.users=users;
        this.booksAllocatedToUsers=booksAllocatedToUsers;
    }

    public BibliotecaApp(Catalog<Book> inStockBooks, Catalog<Movie> inStockMovies, Collection<User> users, Collection<Pair<Book,User>> booksAllocatedToUsers, BufferedReader inStream) // Constructor for testing purpose only
    {
        this.inStockBooks=inStockBooks;
        this.inStockMovies=inStockMovies;
        this.users=users;
        this.booksAllocatedToUsers=booksAllocatedToUsers;
        this.ioHandler = new IOHandler(inStream);
    }

    public void printWelcomeMessage()
    {
        ioHandler.printlnToConsole("Welcome to Biblioteca!!!");
    }

    public void checkoutMovie() {
        ioHandler.printlnToConsole("Enter the name of the movie : ");
        String name =ioHandler.readString();
        Movie res= inStockMovies.searchItemByName(name);
        if(res!=null) {
            inStockMovies.deleteItemFromCatalog(res);
            ioHandler.printlnToConsole("Thank you! Enjoy the movie");
        }
        else {
            ioHandler.printlnToConsole("That movie is not available");
        }

    }

    public void checkoutBook() {
        ioHandler.printlnToConsole("Enter the name of the book : ");
        String name= ioHandler.readString();
        Book res = inStockBooks.searchItemByName(name);
        if(res!=null) {
            inStockBooks.deleteItemFromCatalog(res);
            booksAllocatedToUsers.add(new Pair<Book,User>(res,LoggedInUser));
            ioHandler.printlnToConsole("Thank you! Enjoy the book");
        }
        else {
            ioHandler.printlnToConsole("That book is not available.");
        }
    }

    public void returnBook() {
        ioHandler.printlnToConsole("Enter the name of the book : ");
        String name= ioHandler.readString();
        Book res=null;
        for(Pair<Book,User> batu: booksAllocatedToUsers) {
            if(batu.getKey().getName().equals(name)) {
                res=batu.getKey();
                booksAllocatedToUsers.remove(batu);
                break;
            }
        }
        if(res!=null) {
            inStockBooks.addItemToCatalog(res);
            ioHandler.printlnToConsole("Thank you for returning the book.");
        }
        else {
            ioHandler.printlnToConsole("That is not a valid book to return.");
        }
    }

    public User userLogin() {
        ioHandler.printlnToConsole("Enter the library ID (xxx-xxxx) : ");
        String libraryID=ioHandler.readString();
        boolean userExistsInSystem = false;
        for(User user:users) {
            if(user.getLibraryID().equals(libraryID)) {
                userExistsInSystem=true;
                for(int i=0;i<3;i++) {
                    ioHandler.printlnToConsole("Enter the password : ");
                    char[] password = System.console().readPassword(); //production code
                    //char[] password = ioHandler.readString().toCharArray(); //test code
                    if (user.authenticateUser(password)) {
                        ioHandler.printlnToConsole("You have successfully logged in...");
                        LoggedInUser=user;
                        return user;
                    }
                    else {
                        ioHandler.printlnToConsole("Incorrect password!!! " + (2-i) + " chances left\n");
                    }
                }
            }
        }
        if(userExistsInSystem) {
            ioHandler.printlnToConsole("Max try limit reached!! App will now exit!!!");
        }
        else {
            ioHandler.printlnToConsole("Invalid username");
        }
        return null;
    }

    private void printCheckoutsByUsers() {
        if(LoggedInUser.getAuthorityLevel()==1) { //check if the logged in user is admin/librarian
            ioHandler.printlnToConsole("   Book Name\t\t User Name(email)\tContact Number");
            int i = 1;
            for (Pair<Book, User> batu : booksAllocatedToUsers) {
                ioHandler.printlnToConsole(i++ + ". " + batu.getKey().getName() + "\t\t" + batu.getValue().getUserSummary());
            }
        }
        else {
            ioHandler.printlnToConsole("Acess Denied");
        }
    }

    private void userLogOut() {
        LoggedInUser = null;
        ioHandler.printlnToConsole("You have been successfully logged out");
        LoggedInUser=userLogin();
    }

    public User getLoggedInUser(){
        return LoggedInUser;
    }

    public void performSelectedOption(int optionNumber)
    {
        switch(optionNumber) {
            case 1: ioHandler.printlnToConsole("Books currently available in library : ");
                    ioHandler.printlnToConsole("   Book Name\tAuthor Name\t\tPublishing Date");
                    inStockBooks.printItemList();
                    break;
            case 2: checkoutBook();
                    break;
            case 3: returnBook();
                    break;
            case 4: ioHandler.printlnToConsole("Movies currently available in library : ");
                    ioHandler.printlnToConsole("   Movie Name(Year) by Director Name\t\tRatings");
                    inStockMovies.printItemList();
                    break;
            case 5: checkoutMovie();
                    break;
            case 6: userLogOut();
                    break;
            case 7: // System.exit(0); //Production code
                    ioHandler.printlnToConsole("Quit"); //Test code
                    break;
            case 8: printCheckoutsByUsers();
                    break;
        }
    }

}
